/**
 * 2025/01/01 - 2025/12/31
 */
package com.snail.starter.utils.rest;

import com.snail.starter.commons.error.CommonErrorCode;
import com.snail.starter.commons.exception.BizException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.function.Supplier;

/**
 * @author zgadmin
 * @date 2025/8/26 19:25
 */
@Slf4j
@Component
public class RestTemplateHolder {

    @Resource
    RestTemplate restTemplate;

    public <RES> RES httpInvoke(HttpContextSupplier<RES> contextSupplier, Supplier<BizException> exceptionSupplier) {
        return httpInvoke(contextSupplier.httpContext(), exceptionSupplier.get());
    }

    public <RES> RES httpInvoke(HttpContext<?, RES> httpContext, BizException bizException) {
        long start = System.currentTimeMillis();
        ResponseEntity<RES> responseEntity = restTemplate.exchange(httpContext.getUrl(),
                httpContext.getHttpMethod(),
                httpContext.getHttpEntity(),
                httpContext.getResponseType(),
                httpContext.getUriVariables()
        );
        long cost = System.currentTimeMillis() - start;
        if (cost > 3000L) {
            log.info("RestTemplateHolder cost:{}, reportEnginHttpContext:{}", cost, httpContext);
        } else {
            if (log.isDebugEnabled()) {
                log.debug("RestTemplateHolder cost:{}, reportEnginHttpContext:{}", cost, httpContext);
            }
        }
        if (null == responseEntity) {
            log.warn("RestTemplateHolder response error, request:{}", httpContext);
            if (null == bizException) {
                throw BizException.of(CommonErrorCode.HTTP_RESPONSE_ERROR);
            }
            throw bizException;
        }
        if (!responseEntity.getStatusCode().is2xxSuccessful()) {
            if (null == responseEntity.getBody()) {
                log.warn("RestTemplateHolder response http status not 2xx, response body is null, code:{}, request:{}", responseEntity.getStatusCode().value(), httpContext);
            } else {
                log.warn("RestTemplateHolder response http status not 2xx, code:{}, response body:{}, request:{}", responseEntity.getStatusCode().value(), responseEntity.getBody(), httpContext);
            }
            if (null == bizException) {
                throw BizException.of(CommonErrorCode.HTTP_RESPONSE_STATUS_CODE_ERROR);
            } else {
                throw bizException;
            }
        }
        return responseEntity.getBody();
    }

    public interface HttpContextSupplier<RES> {

        HttpContext<?, RES> httpContext();

    }

}